package com.sweet.store;

import com.sweet.entity.MessageBody;
import com.sweet.entity.User;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import org.mapdb.DB;
import org.mapdb.DBMaker;

import java.io.File;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Created by sweet on 2019/1/15.
 * ---------------------------
 */
public class UserStore implements ITransaction {

  private static final UserStore USER_STORE = new UserStore();

  private static final String BASE_PATH = "db/";
  private static final String USER_DB_PATH = BASE_PATH + "user.db";
  private static final DB USER_DB = DBMaker.newFileDB(new File(USER_DB_PATH)).closeOnJvmShutdown().make();

  private static final Map<String, String> USER_MAP = USER_DB.getTreeMap("user-map");
  private static final Map<String, String> OFFLINE_MESSAGE_MAP = USER_DB.getTreeMap("user-offline-messages-map");

  public static UserStore instance() {
    return USER_STORE;
  }

  private UserStore() {
  }

  public Future<Void> register(User user, Vertx vertx) {
    Future<Void> voidFuture = Future.future();
    vertx.executeBlocking(f -> {
      long count = USER_MAP.values().stream().map(i -> new JsonObject(i).mapTo(User.class))
          .filter(u -> u.getPhone().equals(user.getPhone()))
          .count();
      if(count > 0)
        f.fail("该手机号已被注册");
      else {
        USER_MAP.put(user.getId(), user.toJson().toString());
        commit();
        f.complete();
      }
    }, voidFuture);
    return voidFuture;
  }

  public Future<User> login(String phone, String password, Vertx vertx) {
    Future<User> future = Future.future();
    vertx.executeBlocking(f -> {
      Optional<User> optionalUser = USER_MAP.values().stream().map(i -> new JsonObject(i).mapTo(User.class))
          .filter(u -> u.getPhone().equals(phone)).findAny();
      User user = optionalUser.orElse(null);
      if (user == null) {
        f.fail("该手机号暂未注册");
      } else {
        if (user.getPassword().equals(password)) {
          f.complete(user);
        } else {
          f.fail("手机号密码错误");
        }
      }
    }, future);
    return future;
  }

  public Future<User> search(String phone, Vertx vertx) {
    Future<User> future = Future.future();
    vertx.executeBlocking(f -> {
      Optional<User> userOptional = USER_MAP.values().stream().map(i -> new JsonObject(i).mapTo(User.class))
          .filter(u -> u.getPhone().equals(phone)).findAny();
      User user = userOptional.orElse(null);
      if(user == null) {
        f.fail("无结果");
      } else {
        f.complete(user);
      }
    }, future);
    return future;
  }
  @Override
  public void commit() {
    USER_DB.commit();
  }

  @Override
  public void close() {
    commit();
    USER_DB.close();
  }

  public Future<Void> saveMessage(String to, String messageJson, Vertx vertx) {
    Future<Void> future = Future.future();
    vertx.executeBlocking(f -> {
      JsonArray messageArray = new JsonArray(OFFLINE_MESSAGE_MAP.getOrDefault(to, "[]"));
      messageArray.add(messageJson);
      OFFLINE_MESSAGE_MAP.put(to, messageArray.encode());
      commit();
      f.complete();
    }, future);
    return future;
  }

  public Future<List<String>> getOffLineMessage(String userId, Vertx vertx) {
    Future<List<String>> future = Future.future();
    vertx.executeBlocking(f -> {
      List<String> messageBodyList = new JsonArray(OFFLINE_MESSAGE_MAP.getOrDefault(userId, "[]"))
          .stream().map(Object::toString)
          .collect(Collectors.toList());
      f.complete(messageBodyList);
    }, future);
    return future;
  }
}
